package com.linq.cool.beauty.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linq.cool.beauty.domain.*;
import com.linq.cool.beauty.dto.BeautyCouponDTO;
import com.linq.cool.beauty.dto.BeautyCouponQueryDTO;
import com.linq.cool.beauty.mapper.BeautyCouponMapper;
import com.linq.cool.beauty.service.*;
import com.linq.cool.beauty.vo.BeautyCouponVO;
import com.linq.cool.common.constants.Constants;
import com.linq.cool.common.constants.UserConstants;
import com.linq.cool.common.core.exception.BusinessException;
import com.linq.cool.common.core.utils.BeanUtils;
import com.linq.cool.common.core.utils.IdWorker;
import com.linq.cool.common.core.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: yqlin
 * @Date: 2021/2/7 03:22
 * @Description:
 * @Version: 1.0.0
 */

@Service
public class BeautyCouponServiceImpl extends ServiceImpl<BeautyCouponMapper, BeautyCoupon> implements BeautyCouponService {
    @Autowired
    private BeautyCouponProductService beautyCouponProductService;

    @Autowired
    private BeautyCouponProductCategoryService beautyCouponProductCategoryService;

    @Autowired
    private BeautyProductCategoryService beautyProductCategoryService;

    @Autowired
    private BeautyProductService beautyProductService;

    @Autowired
    private IdWorker idWorker;

    @Override
    public IPage<BeautyCoupon> listByPage(IPage<BeautyCoupon> page, BeautyCouponQueryDTO dto) {
        return this.page(page, this.getLambdaQueryWrapper(dto));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveCoupon(BeautyCouponDTO dto) {
        // 卡券号
        final Long couponId = idWorker.nextId();
        BeautyCoupon coupon = new BeautyCoupon();
        BeanUtils.copyProperties(dto, coupon);
        // 设置默认参数  发行量 和 剩余量 默认时一致
        coupon.setId(couponId).setRemainCount(coupon.getPublishCount()).setCreator(SecurityUtils.getUserId());
        if (this.checkNameUnique(coupon)) {
            throw new BusinessException(String.format("%S,卡券名称已存在", dto.getName()));
        }
        // 如果有指定分类  类型 1 添加优惠券-分类关联
        if (UserConstants.StateEnum.COUPON_TYPE_1.getCode().equals(coupon.getType()) && CollectionUtils.isNotEmpty(dto.getProductCategoryList())) {
            List<BeautyCouponProductCategory> couponProductCategoryList = dto.getProductCategoryList().stream().map(e -> new BeautyCouponProductCategory(couponId, e.getId())).collect(Collectors.toList());
            beautyCouponProductCategoryService.saveBatch(couponProductCategoryList);
        }
        // 如果有商品，添加优惠券-商品关联 类型 2
        if (UserConstants.StateEnum.COUPON_TYPE_2.getCode().equals(coupon.getType()) && CollectionUtils.isNotEmpty(dto.getProductList())) {
            List<BeautyCouponProduct> couponProductList = dto.getProductList().stream().map(e -> new BeautyCouponProduct(couponId, e.getId())).collect(Collectors.toList());
            beautyCouponProductService.saveBatch(couponProductList);
        }
        return this.save(coupon);
    }

    @Override
    public BeautyCouponVO getInfo(Long couponId) {
        // 先查询卡券 信息 在更具卡券类型  进行结果返回
        BeautyCoupon coupon = this.getById(couponId);
        if (null == coupon) {
            throw new BusinessException("该卡券不存在");
        }
        BeautyCouponVO vo = new BeautyCouponVO();
        BeanUtils.copyProperties(coupon, vo);
        // 1 指定分类
        if (UserConstants.StateEnum.COUPON_TYPE_1.getCode().equals(coupon.getType())) {
            // 根据卡券id查询所有指定分类信息
            List<BeautyCouponProductCategory> couponProductCategoryList = beautyCouponProductCategoryService.list(new LambdaQueryWrapper<BeautyCouponProductCategory>()
                                                                                                                          .eq(BeautyCouponProductCategory::getCouponId, coupon.getId())
            );
            List<Long> productCategoryIds = new ArrayList<>();
            couponProductCategoryList.forEach(item -> {
                productCategoryIds.add(item.getProductCategoryId());
            });
            List<BeautyProductCategory> productCategoryList = beautyProductCategoryService.listByIds(productCategoryIds);
            return vo.setProductCategoryList(productCategoryList);
        }
        // 2 指定商品
        if (UserConstants.StateEnum.COUPON_TYPE_2.getCode().equals(coupon.getType())) {
            List<BeautyCouponProduct> couponProductList = beautyCouponProductService.list(new LambdaQueryWrapper<BeautyCouponProduct>()
                                                                                                  .eq(BeautyCouponProduct::getCouponId, coupon.getId()));
            List<Long> productIds = new ArrayList<>();
            couponProductList.forEach(item -> {
                productIds.add(item.getProductId());
            });
            List<BeautyProduct> productList = beautyProductService.listByIds(productIds);
            return vo.setProductList(productList);
        }

        // 判断类型
        // 0 全场通用
        return vo;
    }

    @Override
    public boolean removeCoupon(List<Long> couponIds) {
        List<BeautyCoupon> coupons = this.listByIds(couponIds);
        if (CollectionUtils.isNotEmpty(coupons)) {
            coupons.forEach(coupon -> {
                // 1 指定分类
                if (UserConstants.StateEnum.COUPON_TYPE_1.getCode().equals(coupon.getType())) {
                    beautyCouponProductCategoryService.remove(new LambdaQueryWrapper<BeautyCouponProductCategory>()
                                                                      .eq(BeautyCouponProductCategory::getCouponId, coupon.getId())
                    );
                }
                // 2 指定商品
                if (UserConstants.StateEnum.COUPON_TYPE_2.getCode().equals(coupon.getType())) {
                    beautyCouponProductService.remove(new LambdaQueryWrapper<BeautyCouponProduct>()
                                                              .eq(BeautyCouponProduct::getCouponId, coupon.getId()));
                }
            });
        }
        return this.removeByIds(couponIds);
    }

    @Override
    public List<BeautyCoupon> getProductCoupons(Long productId) {
        // 查询商品信息
        BeautyProduct product = beautyProductService.getById(productId);
        // 查询全场通用优惠券
        List<BeautyCoupon> bothCoupons = baseMapper.listByType(UserConstants.StateEnum.COUPON_TYPE_0.getCode());
        // 查询指定分类ID优惠券
        // 查询当前商品所属分类ids
        List<BeautyCoupon> targetProductCategoryCoupons = baseMapper.listByProductCategoryId(product.getProductCategoryId());
        // 查询指定商品优惠券
        List<BeautyCoupon> targetProductCoupons = baseMapper.listByProductId(productId);
        List<BeautyCoupon> coupons = new ArrayList<>();
        coupons.addAll(targetProductCoupons);
        coupons.addAll(bothCoupons);
        coupons.addAll(targetProductCategoryCoupons);
        return coupons;
    }


    private boolean checkNameUnique(BeautyCoupon coupon) {
        Long couponId = null == coupon.getId() ? -1L : coupon.getId();
        BeautyCoupon one = this.getOne(new LambdaQueryWrapper<BeautyCoupon>()
                                               .select(BeautyCoupon::getId, BeautyCoupon::getName)
                                               .eq(BeautyCoupon::getName, coupon.getName())
        );
        // 判断id是否一致 不一致就代表 唯一 false
        return null != one && !couponId.equals(one.getId());
    }


    private LambdaQueryWrapper<BeautyCoupon> getLambdaQueryWrapper(BeautyCouponQueryDTO dto) {
        return new LambdaQueryWrapper<BeautyCoupon>()
                .eq(BeautyCoupon::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
                .eq(StringUtils.checkValNotNull(dto.getId()), BeautyCoupon::getId, dto.getId())
                .eq(StringUtils.checkValNotNull(dto.getStatus()), BeautyCoupon::getStatus, dto.getStatus())
                .like(StringUtils.checkValNotNull(dto.getName()), BeautyCoupon::getName, dto.getName())
                .eq(StringUtils.checkValNotNull(dto.getType()), BeautyCoupon::getType, dto.getType())
                .between(StringUtils.checkValNotNull(dto.getParams().get(Constants.BEGIN_TIME)), BeautyCoupon::getGmtCreate, dto.getParams().get(Constants.BEGIN_TIME), dto.getParams().get(Constants.END_TIME))
                ;
    }
}
